﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Babylon.Toolbox;
using Microsoft.Xna.Framework.Graphics;

namespace Babylon.Importers
{
    public partial class ObjImporter
    {
        readonly List<BasicEffect> effects = new List<BasicEffect>();
        readonly Dictionary<string, Texture2D> loadedTexture2D = new Dictionary<string, Texture2D>();

        void ImportMaterialLibraries(ObjLine materialLine, Func<string, Stream> resourceLocator, GraphicsDevice device)
        {
            for (int i = 1; i < materialLine.Tokens.Length; i++)
            {
                string fileName = materialLine.Tokens[i];

                Stream source = resourceLocator(fileName);

                Document<MtlLine> mtlDocument = new Document<MtlLine>(source);

                BasicEffect currentEffect = null;

                int currentProgression = 0;

                int total = mtlDocument.Blocks.Sum(lines => lines.Count);
                int scale = 50 / materialLine.Tokens.Length;

                foreach (var lines in mtlDocument.Blocks)
                {
                    foreach (MtlLine line in lines)
                    {
                        currentProgression++;
                        ReportProgressChanged((scale * i - 1) + (currentProgression * scale) / total);

                        switch (line.Header)
                        {
                            case MtlHeader.Material:
                                currentEffect = new BasicEffect(device) { Name = line.Tokens[1] };
                                effects.Add(currentEffect);
                                break;
                            case MtlHeader.DiffuseColor:
                                currentEffect.DiffuseColor = line.ToColor();
                                break;
                            case MtlHeader.DiffuseTexture:
                                currentEffect.DiffuseTexture = LoadTexture(line, resourceLocator, device);
                                break;
                            case MtlHeader.Alpha:
                                currentEffect.Alpha = line.ToFloat();
                                break;
                            case MtlHeader.EmissiveColor:
                                currentEffect.EmissiveColor = line.ToColor();
                                break;
                            case MtlHeader.SpecularColor:
                                currentEffect.SpecularColor = line.ToColor();
                                break;
                            case MtlHeader.SpecularPower:
                                currentEffect.SpecularPower = line.ToFloat();
                                break;
                            case MtlHeader.SpecularTexture:
                                currentEffect.SpecularTexture = LoadTexture(line, resourceLocator, device);
                                break;
                            case MtlHeader.AmbientColor:
                                currentEffect.AmbientColor = line.ToColor();
                                break;
                            case MtlHeader.BumpTexture:
                                currentEffect.BumpTexture = LoadTexture(line, resourceLocator, device);
                                break;
                        }
                    }
                }
            }
        }

        Texture2D LoadTexture(MtlLine line, Func<string, Stream> resourceLocator, GraphicsDevice device)
        {
            Texture2D texture2D;
            string locator = line.Tokens[1].Replace("//", @"\");

            if (!loadedTexture2D.TryGetValue(locator, out texture2D))
            {
                try
                {
                    using (Stream source = resourceLocator(locator))
                    {
                        synchronizationContext.Send(state =>
                                                        {
                                                            texture2D = ContentManager.LoadTexture2D(device, source, true);
                                                        }, null);

                        loadedTexture2D.Add(locator, texture2D);
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format(Strings.UnableToGetContent, locator), ex);
                }
            }
            return texture2D;
        }
    }
}
